package org.springframework.samples.countries.web.translate;

import java.util.HashMap;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.samples.countries.web.bom.Window;

import pikes.ecma.Assignment;
import pikes.ecma.ExpressionStatement;
import pikes.ecma.FunctionCall;
import pikes.ecma.FunctionDeclaration;
import pikes.ecma.Identifier;
import pikes.ecma.MemberPropertyAccess;
import pikes.ecma.NewExpression;
import pikes.ecma.NullLiteral;
import pikes.ecma.ReturnStatement;
import pikes.ecma.SourceElements;
import pikes.ecma.StringLiteral;
import pikes.ecma.VariableStatement;
import pikes.peak.Composite;
import pikes.peak.test.PikesPeakComponentTestCase;
import pikes.samples.countries.ui.peak.BehaviourPage;

public class ASMTranslatorTestCase extends PikesPeakComponentTestCase {

	@Test
	public void noMethod() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			public void empty() {

			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertTrue(sourceElements.isEmpty());
	}

	@Test
	public void emptyMethod() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			public void empty() {

			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		expected.add(new FunctionDeclaration("empty"));
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void emptyWithParameter() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected void emptyWithParameter(String boo) {

			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("emptyWithParameter");
		funcDecl.add("boo");
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void emptyReturn() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		translator.setTranslateEmptyBodyAsReturn(true);
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected void emptyReturn() {
				return;
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("emptyReturn");
		funcDecl.add(new ReturnStatement());
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void setFieldNull() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			protected Window window = new Window();

			@ClientSide
			protected void setFieldNull() {
				window = null;
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("setFieldNull");
		funcDecl.add(new Assignment(new MemberPropertyAccess("this", "window"), new NullLiteral()));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void setLocalNull() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected void setLocalNull() {
				String local = null;
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("setLocalNull");
		funcDecl.add(new VariableStatement("local", new NullLiteral()));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void setParameterNull() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected void setLocalNull(String local) {
				local = null;
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("setLocalNull");
		funcDecl.add("local");
		funcDecl.add(new ExpressionStatement(new Assignment(new Identifier("local"), new NullLiteral())));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void setFieldsFieldNull() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			private Window window = new Window();

			@ClientSide
			protected void setFieldsFieldNull() {
				window.location = null;
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("setFieldsFieldNull");
		funcDecl.add(new ExpressionStatement(new Assignment(new MemberPropertyAccess(new MemberPropertyAccess("this",
				"window"), "location"), new NullLiteral())));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void returnNull() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected Object returnNull() {
				return null;
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("returnNull");
		funcDecl.add(new ReturnStatement(new NullLiteral()));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void returnNewObject() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected Object returnNewObject() {
				return new Object();
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("returnNewObject");
		funcDecl.add(new ReturnStatement(new NewExpression(new Identifier("Object"))));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	public void returnNewString() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected String returnNewString() {
				return new String();
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("returnNewString");
		funcDecl.add(new ReturnStatement(new NewExpression(new Identifier("String"))));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}

	@Test
	@Ignore
	public void returnNewStringWithParam() throws Exception {

		ASMTranslator translator = new ASMTranslator();
		BehaviourPage page = new BehaviourPage() {

			@ClientSide
			protected String returnNewStringWithParameter() {
				return new String("boo");
			}

			@Override
			protected void buildContent(Composite content) {
				// TODO Auto-generated method stub

			}

			@Override
			protected String getTitle() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		Behaviour behaviour = translator.translate(page.getClass());
		SourceElements sourceElements = behaviour.getValue(new HashMap(), pikesPeakRequest.getRequestContext());
		Assert.assertFalse(sourceElements.isEmpty());
		SourceElements expected = new SourceElements();
		FunctionDeclaration funcDecl = new FunctionDeclaration("returnNewStringWithParameter");
		funcDecl.add(new ReturnStatement(new NewExpression(new FunctionCall("String", new StringLiteral("boo")))));
		expected.add(funcDecl);
		Assert.assertEquals(expected, sourceElements);
	}
}
